package org.openapi.parser;

import com.alibaba.fastjson2.JSONObject;
import org.openapi.consts.DirectiveConst;
import org.openapi.vo.RelQuery;
import org.openapi.vo.SqlPager;
import org.openapi.vo.TableQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 解析请求
 * 分页时，默认limit为10
 *
 * 根据ID查询用户模型的一条数据请求示例
 * {
 *   "@table":"user",
 *    "id":2
 * }
 * 单用户模型的分页请求示例
 * {
 *    "id":2
 *    "@table": "USER"
 *    "@pager":{"limit":100, "page":1, "order":"id desc"}
 *    "@exp":{ //字段的条件表达式，不配置就是eq相等
 *        "name":"lk", //like=lk=like '%df%', ll=like 'df%'; rl= like '%df'
 *        "sex":"in", in=in(),
 *     }
 * }
 */
/**
 * 根据ID查询用户及关联模型的一条数据，包括扩展信息和角色请求示例
 *  {
 *      "t": {
 *          "@table":"user",
 *          "id":2,
 *      },
 *      "d":{
 *          "@table":"user_detail",
 *           "userId":"@t.id"
 *       },
 *       "role":{
 *          "@table":"user_role",
 *           "userId":"@t.id"
 *           "@pager":{"limit":100}
 *       }
 *  }
 */

/**
 * 根据条件查询用户模型的数据，包括扩展信息和角色请求示例
 *  {
 *      "t": { //查询条件示例
 *          "@table":"user",
 *          "account":"admin", //eq
 *          "name":"测试", //like %df%
 *          "sex|in":['1','2'] //in 指定的值之内
 *          "age":[], //between and,查询两个数值之间的值
 *          "dept_id": "@deptId()", //@deptId()是取当前用户的组织ID
 *          "@exp":{ //字段的条件表达式，不配置就是eq相等
 *              "name":"lk", //like=lk=like '%df%', ll=like 'df%'; rl= like '%df'
 *              "sex":"in", in=in(),
 *              "age":"bt", //bt=between 1 and 2
 *              "dept_id":"sql", //子查询，代码是后台设置的查询语句
 *              "other":"" // gt<, gte >=,lt<,lte<=,neq!=,eq=,sql='code'内置子查询
 *          }
 *      },
 *      "t1":{ //指令示例
 *          "@table":"user_detail",
 *          "@column":"field1,field2:alias2,field3",//当前表的字段和别名
 *          "@having":"field1,field2:alias2,field3",//当前表的字段和别名
 *          "@schema":"sys", //模式
 *          "@combine":"age OR name AND sex", //条件组合,这里配置的自动组合，没有配置的用AND组合
 *          "@join":"LEFT t1.userId = t.id", //联表配置，LEFT|RIGHT开头，没有默认内联接
 *       },
 *       "@pager":{ //分页参数
 *           "limit":10,
 *           "page":1,
 *           "order":"@User.id DESC", //排序
 *       }
 *  }
 */

public class QueryParser {
    private static final Logger log = LoggerFactory.getLogger(QueryParser.class);

    /**
     * 解析查询条件
     * @param paramStr
     * @return
     */
    public static TableQuery parse(String paramStr){
        JSONObject params = JSONObject.parseObject(paramStr);
        //判断是否为单表模式
        if(params.containsKey(DirectiveConst.TABLE)){
            return parseTable(params);
        }else{
            return parseRel(params);
        }
    }

    /**
     * 解析多表查询
     * @param params
     * @return
     */
    public static RelQuery parseRel(JSONObject params){
        RelQuery query = new RelQuery();

        // 解析主分页
        if(params.containsKey(DirectiveConst.PAGER)) {
            SqlPager pager = parsePager(params.getJSONObject(DirectiveConst.PAGER));
            query.setPager(pager);
            params.remove(DirectiveConst.PAGER);
        }

        //解析查询条件
        int i = 1;
        for(String alias:params.keySet()){
            JSONObject tableParam = params.getJSONObject(alias);
            TableQuery table = new TableQuery();
            // 别名
            if(tableParam.containsKey(DirectiveConst.ALIAS)){
                table.setAlias(tableParam.getString(DirectiveConst.ALIAS));
                tableParam.remove(DirectiveConst.ALIAS);
            }else{
                table.setAlias(alias);
            }
            // 数据表名
            table.setTable(tableParam.getString(DirectiveConst.TABLE));
            tableParam.remove(DirectiveConst.TABLE);

            //内部分页
            if(tableParam.containsKey(DirectiveConst.PAGER)) {
                SqlPager pager = parsePager(tableParam.getJSONObject(DirectiveConst.PAGER));
                table.setPager(pager);
                tableParam.remove(DirectiveConst.PAGER);
            }
            parseTable(params.getJSONObject(alias), table);
            query.addTable(table);
        }
        return query;
    }

    /**
     * 解析单表查询
     * @param tableParam
     * @return
     */
    public static TableQuery parseTable(JSONObject tableParam){
        TableQuery table = new TableQuery();
        table.setTable(tableParam.getString(DirectiveConst.TABLE));
        tableParam.remove(DirectiveConst.TABLE);

        // 别名
        if(tableParam.containsKey(DirectiveConst.ALIAS)){
            table.setAlias(tableParam.getString(DirectiveConst.ALIAS));
            tableParam.remove(DirectiveConst.ALIAS);
        }else{
            table.setAlias("t");
        }

        //内部分页
        if(tableParam.containsKey(DirectiveConst.PAGER)) {
            SqlPager pager = parsePager(tableParam.getJSONObject(DirectiveConst.PAGER));
            table.setPager(pager);
            tableParam.remove(DirectiveConst.PAGER);
        }
        parseTable(tableParam, table);
        return table;
    }

    /**
     * 解析一个表的查询条件
     * @param params
     * @param table
     */
    public static void parseTable(JSONObject params, TableQuery table){
        for(String k:params.keySet()){
            if(DirectiveConst.COLUMN.equalsIgnoreCase(k)){
                table.setColumn(params.getString(DirectiveConst.COLUMN));
            }else if(DirectiveConst.GROUP.equalsIgnoreCase(k)){
                table.setGroup(params.getString(DirectiveConst.GROUP));;
            }else if(DirectiveConst.JOIN.equalsIgnoreCase(k)){
                table.setJoin(params.getString(DirectiveConst.JOIN).trim());;
            }else if(DirectiveConst.HAVING.equalsIgnoreCase(k)){
                table.setHaving(params.getString(DirectiveConst.HAVING));;
            }else if(DirectiveConst.SCHEMA.equalsIgnoreCase(k)){
                table.setSchema(params.getString(DirectiveConst.SCHEMA));;
            }else if(DirectiveConst.COMBINE.equalsIgnoreCase(k)){
                table.setCombine(params.getString(DirectiveConst.COMBINE));;
            }else if(DirectiveConst.EXP.equalsIgnoreCase(k)){
                table.setExps(params.getJSONObject(DirectiveConst.EXP));;
            }else if(k.startsWith("@")){
                System.err.println("不支持的指令" + k);
            }else if(params.get(k) != null){
                table.addData(k, params.get(k));
            }
        }
    }

    /**
     * 解析分页
     * @param param
     * @return
     */
    public static SqlPager parsePager(JSONObject param){
        SqlPager pager = new SqlPager();

        if(param.containsKey(DirectiveConst.LIMIT)){
            pager.setLimit(param.getInteger(DirectiveConst.LIMIT));
        }else{
            pager.setLimit(10);
        }
        if(param.containsKey(DirectiveConst.PAGE)){
            pager.setPage(param.getInteger(DirectiveConst.PAGE));
        }else{
            pager.setPage(1);
        }

        if(param.containsKey(DirectiveConst.ORDER)){
            pager.setOrder(param.getString(DirectiveConst.ORDER));
        }
        pager.setOffset((pager.getPage() - 1) * pager.getLimit());
        return pager;
    }

}
